home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / less_237.zip / less_237 / charset.c < prev    next >
C/C++ Source or Header  |  1994-08-28  |  6KB  |  287 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Functions to define the character set
  30.  * and do things specific to the character set.
  31.  */
  32.  
  33. #include "less.h"
  34. #if HAVE_LOCALE
  35. #include <locale.h>
  36. #include <ctype.h>
  37. #endif
  38.  
  39. /*
  40.  * Predefined character sets,
  41.  * selected by the LESSCHARSET environment variable.
  42.  */
  43. struct charset {
  44.     char *name;
  45.     char *desc;
  46. } charsets[] = {
  47.     { "ascii",    "8bcccbcc18b95.b"        },
  48.     { "latin1",    "8bcccbcc18b95.33b."        },
  49.     { "dos",    "8bcccbcc12bc5b95.98b.b"    },
  50.     { "koi8-r",    "8bcccbcc18b95.b128."        },
  51.     { NULL }
  52. };
  53.  
  54. #define    IS_BINARY_CHAR    01
  55. #define    IS_CONTROL_CHAR    02
  56.  
  57. static char chardef[256];
  58. static char *binfmt = NULL;
  59. public int binattr = AT_BLINK;
  60.  
  61.  
  62. /*
  63.  * Define a charset, given a description string.
  64.  * The string consists of 256 letters,
  65.  * one for each character in the charset.
  66.  * If the string is shorter than 256 letters, missing letters
  67.  * are taken to be identical to the last one.
  68.  * A decimal number followed by a letter is taken to be a 
  69.  * repetition of the letter.
  70.  *
  71.  * Each letter is one of:
  72.  *    . normal character
  73.  *    b binary character
  74.  *    c control character
  75.  */
  76.     static void
  77. ichardef(s)
  78.     char *s;
  79. {
  80.     register char *cp;
  81.     register int n;
  82.     register char v;
  83.  
  84.     n = 0;
  85.     v = 0;
  86.     cp = chardef;
  87.     while (*s != '\0')
  88.     {
  89.         switch (*s++)
  90.         {
  91.         case '.':
  92.             v = 0;
  93.             break;
  94.         case 'c':
  95.             v = IS_CONTROL_CHAR;
  96.             break;
  97.         case 'b':
  98.             v = IS_BINARY_CHAR|IS_CONTROL_CHAR;
  99.             break;
  100.  
  101.         case '0': case '1': case '2': case '3': case '4':
  102.         case '5': case '6': case '7': case '8': case '9':
  103.             n = (10 * n) + (s[-1] - '0');
  104.             continue;
  105.  
  106.         default:
  107.             error("invalid chardef", NULL_PARG);
  108.             quit(1);
  109.             /*NOTREACHED*/
  110.         }
  111.  
  112.         do
  113.         {
  114.             if (cp >= chardef + sizeof(chardef))
  115.             {
  116.                 error("chardef longer than 256", NULL_PARG);
  117.                 quit(1);
  118.                 /*NOTREACHED*/
  119.             }
  120.             *cp++ = v;
  121.         } while (--n > 0);
  122.         n = 0;
  123.     }
  124.  
  125.     while (cp < chardef + sizeof(chardef))
  126.         *cp++ = v;
  127. }
  128.  
  129. /*
  130.  * Define a charset, given a charset name.
  131.  * The valid charset names are listed in the "charsets" array.
  132.  */
  133.     static int
  134. icharset(name)
  135.     register char *name;
  136. {
  137.     register struct charset *p;
  138.  
  139.     if (name == NULL || *name == '\0')
  140.         return (0);
  141.  
  142.     for (p = charsets;  p->name != NULL;  p++)
  143.     {
  144.         if (strcmp(name, p->name) == 0)
  145.         {
  146.             ichardef(p->desc);
  147.             return (1);
  148.         }
  149.     }
  150.  
  151.     error("invalid charset name", NULL_PARG);
  152.     quit(1);
  153.     /*NOTREACHED*/
  154. }
  155.  
  156. #if HAVE_LOCALE
  157. /*
  158.  * Define a charset, given a locale name.
  159.  */
  160.     static void
  161. ilocale()
  162. {
  163.     register int c;
  164.  
  165.     setlocale(LC_CTYPE, "");
  166.     for (c = 0;  c < sizeof(chardef);  c++)
  167.     {
  168.         if (isprint(c))
  169.             chardef[c] = 0;
  170.         else if (iscntrl(c))
  171.             chardef[c] = IS_CONTROL_CHAR;
  172.         else
  173.             chardef[c] = IS_BINARY_CHAR|IS_CONTROL_CHAR;
  174.     }
  175. }
  176. #endif
  177.  
  178. /*
  179.  * Define the printing format for control chars.
  180.  */
  181.        public void
  182. setbinfmt(s)
  183.     char *s;
  184. {
  185.     if (s == NULL || *s == '\0')
  186.         s = "*s<%X>";
  187.     /*
  188.      * Select the attributes if it starts with "*".
  189.      */
  190.     if (*s == '*')
  191.     {
  192.         switch (s[1])
  193.         {
  194.         case 'd':  binattr = AT_BOLD;      break;
  195.         case 'k':  binattr = AT_BLINK;     break;
  196.         case 's':  binattr = AT_STANDOUT;  break;
  197.         case 'u':  binattr = AT_UNDERLINE; break;
  198.         default:   binattr = AT_NORMAL;    break;
  199.         }
  200.         s += 2;
  201.     }
  202.     binfmt = s;
  203. }
  204.  
  205. /*
  206.  * Initialize charset data structures.
  207.  */
  208.     public void
  209. init_charset()
  210. {
  211.     register char *s;
  212.  
  213.     s = getenv("LESSBINFMT");
  214.     setbinfmt(s);
  215.     
  216.     /*
  217.      * See if environment variable LESSCHARSET is defined.
  218.      */
  219.     s = getenv("LESSCHARSET");
  220.     if (icharset(s))
  221.         return;
  222.     /*
  223.      * LESSCHARSET is not defined: try LESSCHARDEF.
  224.      */
  225.     s = getenv("LESSCHARDEF");
  226.     if (s != NULL && *s != '\0')
  227.     {
  228.         ichardef(s);
  229.         return;
  230.     }
  231. #if HAVE_LOCALE
  232.     /*
  233.      * Use setlocale.
  234.      */
  235.     ilocale();
  236. #else
  237.     /*
  238.      * Default to "ascii".
  239.      */
  240.     (void) icharset("ascii");
  241. #endif
  242. }
  243.  
  244. /*
  245.  * Is a given character a "binary" character?
  246.  */
  247.     public int
  248. binary_char(c)
  249.     int c;
  250. {
  251.     c &= 0377;
  252.     return (chardef[c] & IS_BINARY_CHAR);
  253. }
  254.  
  255. /*
  256.  * Is a given character a "control" character?
  257.  */
  258.     public int
  259. control_char(c)
  260.     int c;
  261. {
  262.     c &= 0377;
  263.     return (chardef[c] & IS_CONTROL_CHAR);
  264. }
  265.  
  266. /*
  267.  * Return the printable form of a character.
  268.  * For example, in the "ascii" charset '\3' is printed as "^C".
  269.  */
  270.     public char *
  271. prchar(c)
  272.     int c;
  273. {
  274.     static char buf[8];
  275.  
  276.     c &= 0377;
  277.     if (!control_char(c))
  278.         sprintf(buf, "%c", c);
  279.     else if (c == ESC)
  280.         sprintf(buf, "ESC");
  281.     else if (!control_char(c ^ 0100))
  282.         sprintf(buf, "^%c", c ^ 0100);
  283.     else
  284.         sprintf(buf, binfmt, c);
  285.     return (buf);
  286. }
  287.